Hi,大家好,關於side projects ,已經進入尾聲了,我們完成了資料的輸入、顯示,今天要來完成報表製作的功能。那麼讓我們開始吧
一般的系統規劃中,如果有需要列印的需求,多數都是頁面直接印出,但是直接印出的情形,會發現頁面顯示的排列、顏色等與印表機會有不同,因此在商用軟體上,要就是另外設定列印的樣式,或是直接引入商用報表工具來產製報表,因為使用報表工具,具有較容易控制版面、加入總頁數顯示…等功能,因此我通常是使用報表工具來處理列印的需求
在不少商用軟體都會有所謂的報表產生的功能,例如說 .NET平台的 crystal report、jsp平台常用的 Jasper report,都是可以產生商用報表的工具,本身功能強大,可以應付絕大多數的商用情況,但是因為多數都是要另外學習新的報表工具的用法,所以我們這邊採用了另一個簡單 jsreport 來製作報表,該軟體可以做到將 html 渲染成為 pdf,因此對前端人員來說,幾乎沒有學習門檻
使用該工具,需連結至 jsreport官網 下載並安裝,可支援各種平台,依照執行環境下載對應的平台即可,安裝完畢後,報表會使用 5488 port 啟動
報表檔為一般之 html 檔,要傳入資料時可使用 {{參數欄位}} 傳,若要印出陣列中的資料,可以 each 來處理,報表內容如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<style>
.page-break {
display: block;
page-break-before: always;
}
page[size="A4"] {
background: white;
width: 21cm;
height: 29.7cm;
display: block;
margin: 0 auto;
margin-bottom: 0.5cm;
box-shadow: 0 0 0.0cm rgba(0, 0, 0, 0);
}
@media print {
body,
page[size="A4"] {
margin: 0;
box-shadow: 0;
}
}
@font-face {
font-family: 'EUDC';
font-style: normal;
font-weight: 500;
src: url('//220.130.182.55/fonts/eudc_With_mingliu.woff'),
url('//220.130.182.55/fonts/eudc_With_mingliu.woff') format('woff'),
url('//220.130.182.55/fonts/eudc_With_mingliu.ttf') format('truetype');
}
* {
font-family: 'EUDC';
font-size: 14px;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12" style="padding-top: 10px;">
<style>
.tr {
border-top: 1pt solid green;
}
.dr {
border-left: 1pt solid green;
border-right: 1pt solid green;
;
}
.title {
background-color: rgb(152, 253, 152);
border-bottom: 1px solid green;
}
.info {
background-color: rgb(202, 255, 202);
border-bottom: 1px solid green;
}
.txtr {
text-align: right;
}
.inpcc {
background-color: lightyellow;
color: orange;
border-bottom: 1px solid green;
}
.tc {
text-align: center;
}
</style>
<div id="app" class="container">
<h3>問題描述</h3>
<div class="row dr tr">
<div class="col-2 title txtr">問題名稱:</div>
<div class="col-10">{{cases.casedesc}}</div>
</div>
<div class="row dr">
<div class="col-2 title txtr">問題描述:</div>
<div class="col-10">{{cases.caseinfo}}</div>
</div>
<div class="row dr">
<div class="col-2 title txtr">聯絡人:</div>
<div class="col-6">{{cases.fromper}} <a
href="mailto://{{cases.frommail}}">{{cases.frommail}}</a></div>
<div class="col-2 title txtr">聯絡電話:</div>
<div class="col-2">{{cases.fromtel}}</div>
</div>
<div class="row dr">
<div class="col-2 title txtr">登錄時間:</div>
<div class="col-8">{{cases.logdate}}</div>
<div class="col-2">{{cases.casestatus_desc}}</div>
</div>
<hr />
<h3>辦理情形</h3>
{{#each cases.circuits}}
<div class="row ">
<div class="col-2">{{flowsdate}}</div>
<div class="col-2">{{userid}}</div>
<div class="col-5">{{flowdesc}}</div>
<div class="col-2">{{status_desc}}</div>
</div>
{{/each}}
</div>
將檔案儲在routers/report/report.html
最後在 router中新增產出報表的功能,本次範例假設報表是安裝在本機上,因此呼叫jsreport-client,直接指定 127.0.0.1
router.get("/report/:guid", async (req, res, next) => {
try {
let guid = req.params.guid
//讀取資料
let result = await casedao.getSingleCase(guid)
//讀取報表檔案
let report = fs.readFileSync(path.join(__dirname, "report", "report.html"))
// 取報表檔範例
const jsreport = require('jsreport-client')(
"127.0.0.1", "", "");
jsreport.render({
template: {
content: report,
engine: 'handlebars',
recipe: 'phantom-pdf',
phantom: {
//直印
orientation: "portrait",
//頁面大小
format: "A4" //改A4直印
}
},
data: result
}, function (err, out) {
if (err != null) {
console.log(err)
} else {
res.writeHead(200, {
'Content-Type': "application/pdf",
"Content-Disposition": "inline;filename=report.pdf",
});
out.pipe(res);
}
});
} catch (err) {
res.status(500).send(err.message || err)
}
})